using System;
using System.Collections.Generic;
using System.Text;
using SharpMud.Server.Systems;
using SharpMud.Server.Systems.Scripting.Processing;
using SharpMud.Server.Systems.Scripting.Processing.Source;

namespace SharpMud.Server.Systems.Scripting
{
    public class ScriptManager : SharpMud.Server.Systems.PulsarServerSystem, IScriptManager
    {
        List<IScriptCompileContext> _ScriptCompileContexts;
        List<IScriptSourceHandle> _ScriptSources;
        

        protected override void _Dispose()
        {
            foreach (IScriptCompileContext scc in this._ScriptCompileContexts)
            {
                scc.Dispose();
            }
            _ScriptCompileContexts.Clear(); _ScriptCompileContexts = null;
            _ScriptSources.Clear(); _ScriptSources = null;
            
            base._Dispose();
        }

        #region IScriptManager Members

        public IScriptCompileContext[] GetAllCompileContexts()
        {
            return _ScriptCompileContexts.ToArray();
        }

        public IScriptSourceHandle[] GetAllScriptSources()
        {
            return _ScriptSources.ToArray();
        }

        public IScriptCompileContext CreateCompileContext()
        {
            IScriptCompileContext scc = new ScriptCompileContext(this);

            scc.ScriptAdded += new ScriptSourceMovedEventHandler(ScriptCompileContext_ScriptAdded);
            scc.ScriptRemoved += new ScriptSourceMovedEventHandler(ScriptCompileContext_ScriptRemoved);
            scc.Disposed += new EventHandler(ScriptCompileContext_Disposed);

            return scc;
        }

        public IScriptCompileContext CreateCompileContext(params string[] assemblyReferences)
        {
            IScriptCompileContext scc = new ScriptCompileContext(this);

            scc.ScriptAdded += new ScriptSourceMovedEventHandler(ScriptCompileContext_ScriptAdded);
            scc.ScriptRemoved += new ScriptSourceMovedEventHandler(ScriptCompileContext_ScriptRemoved);
            scc.Disposed += new EventHandler(ScriptCompileContext_Disposed);

            foreach (string s in assemblyReferences)
            { scc.AddAssemblyReference(s); }

            return scc;
        }

        void ScriptCompileContext_Disposed(object sender, EventArgs e)
        {
            lock (this._ScriptCompileContexts)
            {
                this._ScriptCompileContexts.Remove(sender as IScriptCompileContext);
            }
        }

        void ScriptCompileContext_ScriptRemoved(IScriptCompileContext sender, ScriptSourceMovedEventArgs e)
        {
            lock (this._ScriptSources)
            {
                this._ScriptSources.Remove(e.ScriptSource);
            }
        }

        void ScriptCompileContext_ScriptAdded(IScriptCompileContext sender, ScriptSourceMovedEventArgs e)
        {
            lock (this._ScriptSources)
            {
                this._ScriptSources.Add(e.ScriptSource);
            }
        }

        #endregion
    }

    public interface IScriptManager : IServerSystem
    {
        IScriptCompileContext[] GetAllCompileContexts();       
        IScriptSourceHandle[]   GetAllScriptSources();

        IScriptCompileContext CreateCompileContext();
        IScriptCompileContext CreateCompileContext(params string[] assemblyReferences);
    }
}
